package com.gec.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public abstract class DBUtil<T> {

	Connection conn = null;
	PreparedStatement pst = null;
	ResultSet rs = null;

	public Connection getConn() {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dks?useSSL=false&&useUnicode=true&&characterEncoding=UTF-8&&serverTimezone=GMT", "root",
					"1234");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}

	// 通用更新模板方法
	//obj就是 ？的参数 我们将？的参数放到了 这个集合
	public boolean update(String sql, List<Object> obj) {
		int row = 0;
		try {
			//prepareStatement返回一个能够传输sql语句到数据库中执行的方法
			pst = getConn().prepareStatement(sql);
			//obj表示要传入sql语句的参数信息
			//insert into book values(?,?,?,?)   ?占位符表示这里的参数是可以替换的
			if (obj != null) {
				//当sql语句需要传入参数的时候 就按顺序取出来然后放到 sql语句中
				for (int i = 0; i < obj.size(); i++) {
					pst.setObject(i + 1, obj.get(i));
				}
			}
			//执行修改类型的sql语句
			row = pst.executeUpdate();
			if (row > 0)
				return true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			getClose(conn, pst, rs);
		}
		return false;
	}

	// 通用查询模板方法
	//Object...  表示这里可以传入0个或者多个 对象进来
	public List<T> query(String sql, Object...obj) {
		List<T> list = new ArrayList<>();
		try {
			//prepareStatement返回一个能够传输sql语句到数据库中执行的方法
			pst = getConn().prepareStatement(sql);
			//obj表示要传入sql语句的参数信息
			//select * from book where id = ? 条件查询的参数   ?占位符表示这里的参数是可以替换的
			for (int i = 0; i < obj.length; i++) {
				pst.setObject(i + 1, obj[i]);
			}
			//执行查询类型的sql语句 查询的数据 会被返回放到resultSet查询结果集里面
			rs = pst.executeQuery();
			while(rs.next()){
				//将重写方法获取的对象,放入集合中
				list.add(getEntity(rs));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			getClose(conn, pst, rs);
		}
		return list;
	}

	//通过子类实现类,具体重写获取rs的方法
	public abstract T getEntity(ResultSet rs) throws Exception;

	public void getClose(Connection conn, PreparedStatement pst, ResultSet rs) {
		try {
			if (rs != null)
				rs.close();
			if (pst != null)
				pst.close();
			if (conn != null)
				conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
